/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package pl.tom.social.common.sitetool;

import java.text.DateFormat;
import java.text.DateFormatSymbols;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Locale;
import java.util.regex.Pattern;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.htmlparser.Node;
import org.htmlparser.NodeFilter;
import org.htmlparser.Parser;
import org.htmlparser.Tag;
import org.htmlparser.filters.HasAttributeFilter;
import org.htmlparser.filters.NodeClassFilter;
import org.htmlparser.tags.TableRow;
import org.htmlparser.tags.TitleTag;
import org.htmlparser.util.NodeList;
import org.htmlparser.util.ParserException;
import pl.tom.social.common.date.PolishMonths;
import pl.tom.social.common.types.PageEntryType;
import pl.tom.social.dal.entity.SiteEntry;
import pl.tom.social.common.types.PageType;
import pl.tom.social.common.utils.URLTools;
import pl.tom.social.dal.SocialDatabaseFacade;

/**
 *
 * @author Tom
 */
public class OnetTools implements ISiteTools {

	private static final Logger logger = Logger.getLogger(OnetTools.class);
	//TODO fix this
	String[] exludes = {"http://blog.onet.pl", "http://blog.onet.pl/"};
	String[] servers = {"blog.onet.pl"};

	@Override
	public String getCrawlerServer(String url) {
		return url;
	}

	@Override
	public Date getBlogEntryDate(String html) {
		Date result = null;
		Node[] dateNodes = getBlogEntryPart(html, "class", "bl_dataImg edit_ramka12");
		if(dateNodes == null || dateNodes.length == 0) {
			return new Date();
		}
		String strDate = dateNodes[0].toPlainTextString();
		strDate = strDate.trim();
		strDate = strDate.replace("  ", " ");
		String strMonth = strDate.split(" ")[1].toLowerCase();
		try {
			strDate = strDate.replace(strMonth, PolishMonths.valueOf(strMonth).getNumber().toString());
			DateFormat dateFormat = new SimpleDateFormat("dd MM yyyy", DateFormatSymbols.getInstance(new Locale("pl")));
			result = dateFormat.parse(strDate);
		} catch(Exception ex) {
			logger.log(Level.ERROR, null, ex);
			result = new Date();
		}
		return result;
	}

	@Override
	public String getBlogEntryTitle(String url, String html) {
		try {
			Parser parser = new Parser(html);
			NodeFilter filter = new NodeClassFilter(TitleTag.class);
			NodeList list = parser.extractAllNodesThatMatch(filter);
			if(list.size() > 0) {
				return list.elementAt(0).toPlainTextString();
			}
		} catch(ParserException ex) {
			logger.log(Level.ERROR, null, ex);
		}
		return null;
	}

	@Override
	public String getBlogEntryBody(String html, PageType pageType) {
		String className;
		switch(pageType) {
			case Comment:
				className = "bl_body";
				break;
			case Home:
				className = "u1_teImg";
				break;
			default:
				className = "bl_bodyImg edit_ramka12";
				break;
		}
		Node[] nodes = getBlogEntryPart(html, "class", className);
		switch(pageType) {
			case Comment:
				if(nodes.length > 1) {
					return nodes[1].toHtml();
				} else if(nodes.length == 1) {
					return nodes[0].toHtml();
				}
				break;
			default:
				if(nodes.length > 0) {
					return nodes[0].toHtml();
				}
		}
		return "";
	}

	@Override
	public String getHtmlAsText(String res) {
		try {
			Parser parser = new Parser(res);
			NodeList nodeList = parser.parse(null);
			return nodeList.asString();
		} catch(ParserException ex) {
			logger.log(Level.ERROR, null, ex);
		}
		return "";
	}

	@Override
	public Collection<String> filterLinks(Collection<String> links) {
		HashSet<String> result = new HashSet<String>();
		for(Iterator<String> it = links.iterator(); it.hasNext();) {
			String link = it.next();
			boolean ok = true;
			for(int i = 0; i < exludes.length; i++) {
				if(link.contains(exludes[i])) {
					ok = false;
				}
			}
			if(!ok) {
				continue;
			}
			ok = false;
			for(int i = 0; i < servers.length; i++) {
				if(link.contains(servers[i])) {
					ok = true;
				}
			}
			if(!ok) {
				continue;
			} else {
				result.add(URLTools.clean(link));
			}
		}
		return result;
	}

	@Override
	public PageType getPageType(String url, String blogUrl) {
		if(url.endsWith("//")) {
			url = url.substring(0, url.length() - 1);
		}
		String[] bits = url.split("/");
		String end = bits[bits.length - 1];

		Pattern entry = Pattern.compile(".*ID\\d*,n", Pattern.CASE_INSENSITIVE);
		Pattern comment = Pattern.compile("[0-9,]*forum.html", Pattern.CASE_INSENSITIVE);

		if(entry.matcher(end).matches()) {
			return PageType.Entry;
		} else if(comment.matcher(end).matches()) {
			return PageType.Comment;
		} else if(URLTools.compareUrl(url, blogUrl)) {
			return PageType.Home;
		}
		logger.log(Level.DEBUG, "Entry type set to \'other\' for url " + url);
		return PageType.Other;
	}

	@Override
	public SiteEntry getEntryFromComment(String body) {
		SiteEntry entry = null;
		String url = null;
		Node[] nodes = getBlogEntryPart(body, "class", "bl_tImg  edit_ramka12");
		if(nodes.length > 0) {
			for(int i = 0; i < nodes.length; i++) {
				NodeList titleList = new NodeList(nodes[i]);
				NodeFilter filter = new HasAttributeFilter("href");
				NodeList urls = titleList.extractAllNodesThatMatch(filter, true);
				if(urls.size() > 0) {
					url = ((Tag) urls.elementAt(0)).getAttribute("href");
					break;
				}
			}
		}

		try {
			SocialDatabaseFacade db = new SocialDatabaseFacade();
			entry = db.getSiteEntry(url);
		} catch(Exception ex) {
			logger.log(Level.ERROR, null, ex);
		}

		return entry;
	}

	@Override
	public Date getCommentDate(String body) {
		try {
			Parser parser = new Parser(body);
			NodeFilter filter = new NodeClassFilter(TableRow.class);
			NodeList list = parser.extractAllNodesThatMatch(filter);
			String[] commentSig = list.elementAt(5).toPlainTextString().trim().split(",");
			String strDate = commentSig[commentSig.length - 1].trim();
			DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm", DateFormatSymbols.getInstance(new Locale(
					"pl")));
			return dateFormat.parse(strDate);
		} catch(Exception ex) {
			logger.log(Level.ERROR, null, ex);
		}
		return new Date();
	}

	@Override
	public String getCommentAuthor(String body) {
		try {
			Parser parser = new Parser(body);
			NodeFilter filter = new NodeClassFilter(TableRow.class);
			NodeList list = parser.extractAllNodesThatMatch(filter);
			String commentSig = list.elementAt(5).toPlainTextString().trim();
			String[] commentSigBits = commentSig.split(",");
			String date = commentSigBits[commentSigBits.length - 1];
			return list.elementAt(5).toPlainTextString().substring(0, commentSig.length() - date.length() - 1).trim();
		} catch(NullPointerException ex) {
			logger.log(Level.INFO, "Author not found", ex);
		} catch(Exception ex) {
			logger.log(Level.ERROR, null, ex);
		}
		return null;
	}

	@Override
	public PageEntryType getEntryType(String url) {
		return PageEntryType.Standard;
	}

	@Override
	public String[] getExcludes() {
		return exludes;
	}

	@Override
	public String[] getServers() {
		return servers;
	}

	private Node[] getBlogEntryPart(String res, String attribute, String value) {
		Node[] result = null;
		try {
			Parser parser = new Parser(res);
			HasAttributeFilter filter = new HasAttributeFilter(attribute, value);
			NodeList list = parser.extractAllNodesThatMatch(filter);
			result = list.toNodeArray();
		} catch(ParserException ex) {
			logger.log(Level.ERROR, null, ex);
		}
		if(result != null && result.length == 0) {
			logger.log(Level.WARN, "No results");
		}
		return result;
	}
}
